# gplugs/httpwatch.py
#
#

""" watch websites for changes. """


## gozerbot imports

from gozerbot.commands import cmnds
from gozerbot.datadir import datadir
from gozerbot.fleet import fleet
from gozerbot.generic import geturl2
from gozerbot.periodical import periodical
from gozerbot.persist.persistconfig import PersistConfig
from gozerbot.persist.pdod import Pdod
from gozerbot.examples import examples
from gozerbot.plughelp import plughelp
from gozerbot.tests import tests
import gozerbot.threads.thr as thr

## basic imports

import hashlib
import os

## plughelp

plughelp.add('httpwatch', 'periodically check urls')

## defines

cfg = PersistConfig()
cfg.define('sleep', 300)
cfg.define('run', True)

## HttpWatch class

class HttpWatch(Pdod):
    
    pid = None

    def __init__(self):
        self.datadir = datadir + os.sep + 'plugs' + os.sep + 'httpwatch'
        Pdod.__init__(self, os.path.join(self.datadir, 'httpwatch.data'))
        if not 'urls' in self.data: self.data['urls'] = {}
        if not 'send' in self.data: self.data['send'] = {} ; self.save()

    def start(self):
        self.pid = periodical.addjob(cfg.get('sleep'), 0, self.peek, 'httpwatch', 'httpwatch')
 
    def stop(self):
        if self.pid: periodical.killjob(self.pid) ; self.pid = None

    def peek(self, *args, **kwargs):
        if not self.data['urls']: return
        for url in self.data['urls']:
            try: checksum = self.checksum(url)
            except: continue
            if checksum != self.data['urls'][url]:
                self.data['urls'][url] = checksum
                self.announce(url)
        self.save()
        return self.data['urls']

    def checksum(self, url):
        data = geturl2(url)
        return hashlib.md5.new(data).hexdigest()

    def announce(self, url):
        for name in self.data['send'][url]:
            bot = fleet.byname(name)
            for chan in self.data['send'][url][name]:
                bot.say(chan, '%s changed (new checksum: %s)' % (url, self.data['urls'][url]))

    def add(self, url, name, chan):
        if not url in self.data['urls']:
            self.data['urls'][url] = ''
        if not url in self.data['send']:
            self.data['send'][url] = {}
        if not name in self.data['send'][url]:
            self.data['send'][url][name] = []
        if not chan in self.data['send'][url][name]:
            self.data['send'][url][name].append(chan)
            self.save()

    def remove(self, url, name, chan):
        if url not in self.data['send']:
            return
        if name not in self.data['send'][url]:
            return
        if chan in self.data['send'][url][name]:
            self.data['send'][url][name].remove(chan)
        if len(self.data['send'][url][name]) == 0:
            del self.data['send'][url][name]
        if len(self.data['send'][url]) == 0:
            del self.data['send'][url]
        self.save()

## define2

httpwatch = HttpWatch()

## init function

def init():
    if cfg.get('run'): thr.start_new_thread(httpwatch.start, ())
    return 1

## shutdown function

def shutdown():
    if httpwatch.pid: httpwatch.stop()
    return 1

## httpwatch-add command

def handle_httpwatch_add(bot, ievent):
    """ add an url to watch. """
    if len(ievent.args) != 1: ievent.missing('<url>')
    else:
        try:
            geturl2(ievent.args[0])
            httpwatch.add(ievent.args[0], bot.name, ievent.channel)
            ievent.reply('http watcher added')
        except Exception, e: ievent.reply('failed to add: %s' % (str(e),))

cmnds.add('httpwatch-add', handle_httpwatch_add, 'OPER')
examples.add("httpwatch-add", "add an url to the httpwatcher", "httpwatch-add http://gozerbot.org")
tests.add('httpwatch-add http://gozerbot.org')

## httpwatch-del command

def handle_httpwatch_del(bot, ievent):
    """ delete an url from the watcher. """
    if len(ievent.args) != 1: ievent.missing('<url>')
    else:
        httpwatch.remove(ievent.args[0], bot.name, ievent.channel)
        ievent.reply('http watcher removed')

cmnds.add('httpwatch-del', handle_httpwatch_del, 'OPER')
examples.add("httpwatch-del", "delete url from http watcher", "httpwatch-del http://gozerbot.org")
tests.add('httpwatch-del http://gozerbot.org')

## httpwatch-list command

def handle_httpwatch_list(bot, ievent):
    """ show list of watched urls. """
    ievent.reply(str(httpwatch.data['send']))

cmnds.add('httpwatch-list', handle_httpwatch_list, 'OPER')
tests.add('httpwatch-list')

## httpwatch-peek command

def handle_httpwatch_peek(bot, ievent):
    """ take a peek on all watched urls. """
    ievent.reply('running httpwatch.peek()')
    ievent.reply(str(httpwatch.peek()))

cmnds.add('httpwatch-peek', handle_httpwatch_peek, 'OPER')
tests.add('httpwatch-peek')

## httpwatch-start command

def handle_httpwatch_start(bot, ievent):
    """ start the http watcher. """
    if httpwatch.pid: ievent.reply('watcher already running (pid: %s)' % (str(httpwatch.pid),))
    else: httpwatch.start() ; ievent.reply('watcher started')

cmnds.add('httpwatch-start', handle_httpwatch_start, 'OPER')
tests.add('httpwatch-start')

## httpwatch-stop command

def handle_httpwatch_stop(bot, ievent):
    """ stop the http watcher. """
    if httpwatch.pid: httpwatch.stop() ; ievent.reply('watcher stopped')
    else: ievent.reply('watcher not running')

cmnds.add('httpwatch-stop', handle_httpwatch_stop, 'OPER')
tests.add('httpwatch-stop')

#### BHJTW 22-01-2012
